package cn.cleanarch.infra.idp.pms.utils;

import cn.cleanarch.infra.idp.pms.constants.StorageConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;
import java.util.zip.ZipInputStream;

/**
 * 文件解压缓存管理器
 * 用于管理已解压的文件，避免重复解压
 */
@Component
public class ExtractCacheManager {
    
    private static final Logger logger = LoggerFactory.getLogger(ExtractCacheManager.class);
    
    // 解压基础目录
    private static final String EXTRACT_BASE_DIR = StorageConstants.EXTRACT_BASE_PATH;
    
    // 缓存锁Map，用于防止并发解压
    private final ConcurrentHashMap<Long, ReentrantLock> extractLocks = new ConcurrentHashMap<>();
    
    /**
     * 获取文件解压路径
     * @param fileId 文件ID
     * @return 解压路径
     */
    public String getExtractPath(Long fileId) {
        String extractPath = EXTRACT_BASE_DIR + "/" + fileId;
        logger.info("获取文件解压路径 - 文件ID: {}, 解压路径: {}", fileId, extractPath);
        return extractPath;
    }
    
    /**
     * 检查文件是否已解压
     * @param versionId 文件ID
     * @return 是否已解压
     */
    public boolean isExtracted(Long versionId) {
        String extractPath = getExtractPath(versionId);
        Path path = Paths.get(extractPath);
        boolean exists = Files.exists(path) && Files.isDirectory(path);
        logger.info("检查文件是否已解压 - 文件ID: {}, 解压路径: {}, 是否已解压: {}", versionId, extractPath, exists);
        return exists;
    }
    
    /**
     * 获取文件解压锁
     * @param versionId 文件ID
     * @return 解压锁
     */
    public ReentrantLock getExtractLock(Long versionId) {
        logger.info("获取文件解压锁 - 文件ID: {}", versionId);
        ReentrantLock lock = extractLocks.computeIfAbsent(versionId, k -> new ReentrantLock());
        logger.info("获取文件解压锁完成 - 文件ID: {}, 锁实例: {}", versionId, System.identityHashCode(lock));
        return lock;
    }
    
    /**
     * 清理过期解压文件
     * @param maxAge 最大保留时间（毫秒）
     */
    public void cleanupExpiredFiles(long maxAge) {
        logger.info("开始清理过期解压文件 - 最大保留时间: {} 毫秒", maxAge);
        
        try {
            Path basePath = Paths.get(EXTRACT_BASE_DIR);
            logger.info("基础路径: {}, 是否存在: {}", basePath, Files.exists(basePath));
            
            if (!Files.exists(basePath)) {
                logger.info("基础路径不存在，无需清理");
                return;
            }
            
            long currentTime = System.currentTimeMillis();
            logger.info("当前时间: {}", currentTime);
            
            Files.walk(basePath)
                .filter(Files::isDirectory)
                .forEach(dir -> {
                    try {
                        long lastModified = Files.getLastModifiedTime(dir).toMillis();
                        logger.debug("检查目录 - 路径: {}, 最后修改时间: {}, 时间差: {}", 
                                   dir, lastModified, currentTime - lastModified);
                        
                        if (currentTime - lastModified > maxAge) {
                            logger.info("删除过期目录 - 路径: {}, 最后修改时间: {}", dir, lastModified);
                            // 删除目录及其内容
                            deleteDirectory(dir.toFile());
                        }
                    } catch (Exception e) {
                        logger.error("处理目录时发生错误 - 路径: {}", dir, e);
                        // 忽略错误，继续清理
                    }
                });
                
            logger.info("过期文件清理完成");
        } catch (Exception e) {
            logger.error("清理过期解压文件时发生错误", e);
        }
    }
    
    /**
     * 递归删除目录
     * @param directory 要删除的目录
     */
    private void deleteDirectory(File directory) {
        if (directory.exists()) {
            File[] files = directory.listFiles();
            if (files != null) {
                for (File file : files) {
                    if (file.isDirectory()) {
                        deleteDirectory(file);
                    } else {
                        file.delete();
                    }
                }
            }
            directory.delete();
        }
    }
    
    /**
     * 获取缓存统计信息
     * @return 缓存统计信息
     */
    public String getCacheStats() {
        try {
            Path basePath = Paths.get(EXTRACT_BASE_DIR);
            if (!Files.exists(basePath)) {
                return "无缓存文件";
            }
            
            long fileCount = Files.walk(basePath)
                .filter(Files::isDirectory)
                .count();
            
            return String.format("缓存文件数: %d", fileCount);
        } catch (Exception e) {
            return "获取统计信息失败: " + e.getMessage();
        }
    }
}